home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Taifun / Taifun 089 (1989-02-15)(Ossowski, Stefan)(DE)(PD).zip / Taifun 089 (1989-02-15)(Ossowski, Stefan)(DE)(PD).adf / SPUDclock / SPUDclock.c < prev    next >
C/C++ Source or Header  |  1988-12-17  |  33KB  |  912 lines

  1. /*************************************************************************
  2.  *
  3.  *  SPUDclock - This program does a nice little talking alarm clock
  4.  *  
  5.  *  This was written by Robert E. Beaty and H. Bret Young and
  6.  *  are Copyright (C) 1987 by R.E.Beaty and H. Bret Young and
  7.  *  The Man From S.P.U.D.
  8.  *
  9.  *  v1.2
  10.  *************************************************************************/
  11.  
  12. /* Get the necessary include files for this program */
  13. #include <exec/types.h>
  14. #include <exec/exec.h>
  15. #include <devices/narrator.h>
  16. #include <devices/timer.h>
  17. #include <libraries/translator.h>
  18. #include <libraries/dos.h>
  19. #include <intuition/intuition.h>
  20. #include <string.h>
  21.  
  22. /*
  23.  * Here are some necessary defines for processing needs
  24.  */
  25. #define REVISION    1
  26. #define TASK_PRIORITY    0
  27.  
  28. /*
  29.  * Here are some necessary return codes for various routines
  30.  */
  31. #define NORMAL_EXIT        0
  32. #define NORMAL_START        0
  33. #define QUICK_EXIT        -10
  34. #define QUICK_START        -20
  35. #define CANT_OPEN_INTUITION    -100
  36. #define CANT_OPEN_TRANSLATOR    -200
  37. #define CANT_OPEN_NARRATOR    -300
  38. #define CANT_OPEN_TIMER        -400
  39. #define CREATE_PORT_PROBLEMS    -500
  40. #define CREATE_IO_PROBLEMS    -600
  41. #define TRANSLATOR_NOT_WORKING    -700
  42.  
  43. /* 
  44.  * Here are the variable values that come in handy
  45.  */
  46. #define QUARTER_HOUR        1
  47. #define HALF_HOUR        2
  48. #define HOUR            4
  49. #define LITTLE            1
  50. #define BIG            2
  51.  
  52. #define    AM_BIT            (1<<0)
  53. #define PS_BIT            (1<<1)
  54. #define    SA_BIT            (1<<2)
  55. #define    EA_BIT            (1<<3)
  56. #define    AV_BIT            (1<<4)
  57. #define    S_BIT            (1<<5)
  58.  
  59. /* 
  60.  * Here are the global structures
  61.  */
  62. struct timerequest timeReq;    /* this is my conduit to the timer */
  63. struct MsgPort *clockPort = NULL, *writePort = NULL, 
  64.                *replyPort = NULL, *timerPort = NULL;
  65. struct narrator_rb *writeNarrator = NULL;
  66. struct IntuitionBase *IntuitionBase = NULL;
  67. struct Library *TranslatorBase = NULL;
  68. struct DateStamp now;
  69. struct PacketMessage {
  70.     struct Message packet_message;        /* this is for DOS */
  71.     int alarm_mode,        /* this will tell us how often to alarm */
  72.         prestart,        /* this will tell if we prestart the speakers */
  73.         start_alarm,    /* this is the starting time */
  74.         end_alarm,        /* this is the ending time */
  75.         alarm_volume,    /* this is how loud to make it */
  76.         quit_flag;        /* this will tell when to quit */
  77.     char salutation[80];    /* this is a little saying before the time */
  78.         int change_flags,
  79.             changing,
  80.             listing;
  81.     };
  82.  
  83. /* 
  84.  * Here are the global variables
  85.  */
  86. UBYTE *sampleInput, outputString[500];    /* these are for the translator */
  87. SHORT rtnCode, error;
  88. BYTE audChanMasks[4] = { 3, 5, 10, 12 };    /* which channels to use */
  89. int signal, timer_signal, port_signal;    /* where the message came from */
  90. int alarm_mode, quit_flag, prestart, alarm_volume;
  91. int start_alarm, end_alarm, alarm_time;
  92. int hours_24, hours_12, minutes;
  93. char *cp, salutation[80], alarm[120];
  94. struct PacketMessage *incoming, *outgoing;
  95.  
  96.  
  97.  
  98. /************************************************************************
  99.  *
  100.  *  cprintf( why ) - This routine does simple string printing to
  101.  *               the console, and so saves us loading the printf
  102.  *               routines.
  103.  *
  104.  *  This code section was written by Robert E. Beaty and
  105.  *  are Copyright (C) 1987 by R.E.Beaty and The Man From S.P.U.D.
  106.  *
  107.  ************************************************************************/
  108. cprintf( arg )
  109. char *arg;
  110. {
  111.     int length;
  112.  
  113.     length = Write( Output(), arg, strlen(arg) );
  114.     return( length );
  115. }   /* end of cprintf(); */
  116.  
  117.  
  118.  
  119. /************************************************************************
  120.  *
  121.  *  itoa( string, value ) - This routine does simple integer to ascii
  122.  *                  conversion. NOTE: value < 9999 !!
  123.  *
  124.  *  This code section was written by Robert E. Beaty and
  125.  *  are Copyright (C) 1987 by R.E.Beaty and The Man From S.P.U.D.
  126.  *
  127.  ************************************************************************/
  128. void itoa( carg, varg )
  129. char *carg;
  130. int varg;
  131. {
  132.     int place;
  133.  
  134.     /* reset where I am putting this stuff */
  135.     place = 0;
  136.  
  137.     if ( varg > 999 ) {
  138.         /* do the most thousands digit */
  139.         carg[place++] = '0' + (varg/1000);
  140.         varg = varg - (1000*(varg/1000));
  141.     }
  142.     if ( (varg > 99) || (place != 0) ) {
  143.         /* do the hundreds digit */
  144.         carg[place++] = '0' + (varg/100);
  145.         varg = varg - (100*(varg/100));
  146.     }
  147.     if ( (varg > 9) || (place != 0) ) {
  148.         /* do the tens digit */
  149.         carg[place++] = '0' + (varg/10);
  150.         varg = varg - (10*(varg/10));
  151.     }
  152.     /* always do the ones digit */
  153.     carg[place++] = '0' + varg;
  154.  
  155.     /* null terminate this string */
  156.     carg[place] = '\0';
  157. }   /* end of itoa(); */
  158.  
  159.  
  160.  
  161. /************************************************************************
  162.  *
  163.  *  CloseNarrator( why ) - This routine closes up the narrator and
  164.  *                     translator devices nicely.
  165.  *
  166.  *  This code section was written by Robert E. Beaty and
  167.  *  are Copyright (C) 1987 by R.E.Beaty and The Man From S.P.U.D.
  168.  *
  169.  ************************************************************************/
  170. void CloseNarrator( why )
  171. int why;
  172. {
  173.     /* Check to see if this was called by OpenNarrator() */
  174.     if ( why != CANT_OPEN_NARRATOR ) {
  175.         if ( writeNarrator != NULL )
  176.             CloseDevice( writeNarrator );
  177.     }
  178.     /* Just start deleting things if they exist */
  179.     if ( writeNarrator != NULL )
  180.         DeleteExtIO( writeNarrator, sizeof(struct narrator_rb) );
  181.     if ( writePort != NULL )
  182.         DeletePort( writePort );
  183.     if ( TranslatorBase != NULL )
  184.         CloseLibrary( TranslatorBase );
  185. }   /* end of CloseNarrator(); */
  186.  
  187.  
  188.  
  189. /************************************************************************
  190.  *
  191.  *  OpenNarrator() - This routine opens up the narrator and translator
  192.  *               devices nicely. It will return non-FALSE if an error
  193.  *               occured.
  194.  *
  195.  *  This code section was written by Robert E. Beaty and
  196.  *  are Copyright (C) 1987 by R.E.Beaty and The Man From S.P.U.D.
  197.  *
  198.  ************************************************************************/
  199. OpenNarrator( )
  200. {
  201.     int error;
  202.  
  203.     /* Open up the translator first */
  204.     TranslatorBase = (struct Library *) OpenLibrary( "translator.library", REVISION );
  205.     if ( TranslatorBase == NULL )
  206.         return( CANT_OPEN_TRANSLATOR );
  207.         
  208.     /* test it */
  209.     sampleInput = "this is a test.";
  210.     rtnCode = Translate( sampleInput, strlen(sampleInput), outputString, 500 );
  211.     if ( rtnCode != 0 ) {
  212.         CloseLibrary( TranslatorBase );        /* this is open, so close */
  213.         return( TRANSLATOR_NOT_WORKING );
  214.     }   /* end of error checking the translator */
  215.  
  216.     /* Create the port to the Narrator */
  217.     writePort = (struct MsgPort *) CreatePort( "SPUDclock.narrator", TASK_PRIORITY );
  218.     if ( writePort == NULL ) {
  219.         CloseLibrary( TranslatorBase );        /* this is open, so close */
  220.         return( CREATE_PORT_PROBLEMS );
  221.     }   /* end of error checking the port creation */
  222.  
  223.     /* Open an I/O channel to the Narrator */
  224.     writeNarrator = (struct narrator_rb *) CreateExtIO( writePort, sizeof(struct narrator_rb) );
  225.     if ( writeNarrator == NULL ) {
  226.         DeletePort( writePort );        /* this port is open */
  227.         CloseLibrary( TranslatorBase );        /* this is open, so close */
  228.         return( CREATE_IO_PROBLEMS );
  229.     }   /* end of error checking I/O creation */
  230.  
  231.     /* Now set up the defaults for the narrator port */
  232.     writeNarrator->ch_masks = audChanMasks;    /* ... the channel masks */
  233.     writeNarrator->nm_masks = sizeof(audChanMasks);    /* ... the size */
  234.     writeNarrator->message.io_Data = (APTR)outputString;    /* data */
  235.     writeNarrator->mouths = 0;        /* we don't want shapes computed */
  236.     writeNarrator->message.io_Command = CMD_WRITE;    /* output command */
  237.  
  238.     /* Finally, open the narrator device */
  239.     error = OpenDevice( "narrator.device", 0, writeNarrator, TASK_PRIORITY );
  240.     if ( error != 0 ) {
  241.         CloseNarrator( CANT_OPEN_NARRATOR );    /* close it all up */
  242.         return( CANT_OPEN_NARRATOR );
  243.     }   /* end of checking narrator device opening */
  244.     
  245.     /* no errors so return FALSE */
  246.     return( FALSE );
  247. }   /* end of OpenNarrator(); */
  248.  
  249.  
  250.  
  251. /************************************************************************
  252.  *
  253.  *  init( how ) - This routine opens everything up and returns non-FALSE
  254.  *                if something went wrong.
  255.  *
  256.  *  This code section was written by Robert E. Beaty and
  257.  *  are Copyright (C) 1987 by R.E.Beaty and The Man From S.P.U.D.
  258.  *
  259.  ************************************************************************/
  260. init( how )
  261. int how;
  262. {
  263.     int error;
  264.  
  265.     /* Open up Intuition first */
  266.     if ( IntuitionBase == NULL ) {
  267.         IntuitionBase = (struct IntuitionBase *) OpenLibrary( "intuition.library", REVISION );
  268.         if ( IntuitionBase == NULL )
  269.             return( CANT_OPEN_INTUITION );
  270.     }   /* end of opening intuition if needed */
  271.     /* if this is a quick start, then only open up intuition */
  272.     if ( how == QUICK_START ) return( FALSE );
  273.  
  274.     /* Open the communication port to other copies of SPUDclock */
  275.     clockPort = (struct MsgPort *) CreatePort( "SPUDclock", TASK_PRIORITY );
  276.     if ( clockPort == NULL ) {
  277.         CloseLibrary( IntuitionBase );        /* this is open, so close */
  278.         return( CREATE_PORT_PROBLEMS );
  279.     }   /* end of error checking the port creation */
  280.  
  281.     /* Now open the narrator */
  282.     error = OpenNarrator();
  283.     if ( error ) {
  284.         DeletePort( clockPort );
  285.         CloseLibrary( IntuitionBase );
  286.         return( error );
  287.     }   /* end of error checking the narrator opening */
  288.     
  289.     /* Now create the timer */
  290.     timerPort = (struct MsgPort *) CreatePort( "SPUDclock.timer", TASK_PRIORITY );
  291.     if ( timerPort == NULL ) {
  292.         CloseNarrator( CANT_OPEN_TIMER );
  293.         DeletePort( clockPort );
  294.         CloseLibrary( IntuitionBase );        /* this is open, so close */
  295.         return( CREATE_PORT_PROBLEMS );
  296.     }   /* end of error checking the port creation */
  297.  
  298.     error = OpenDevice( TIMERNAME, UNIT_VBLANK, (char *) &timeReq, TASK_PRIORITY );    
  299.     if ( error != 0 ) {
  300.         DeletePort( timerPort );
  301.         CloseNarrator( CANT_OPEN_TIMER );
  302.         DeletePort( clockPort );
  303.         CloseLibrary( IntuitionBase );        /* this is open, so close */
  304.         return( CANT_OPEN_TIMER );
  305.     }
  306.  
  307.     /* Everything is open O.K., so get the signal bits */
  308.     timer_signal = 1 << timerPort->mp_SigBit;
  309.     port_signal = 1 << clockPort->mp_SigBit;
  310.     
  311.     /* ... and set up the timer request structure */
  312.     timeReq.tr_node.io_Message.mn_ReplyPort = timerPort;
  313.     timeReq.tr_node.io_Command = TR_ADDREQUEST;
  314.     timeReq.tr_node.io_Flags = 0;
  315.     timeReq.tr_node.io_Error = 0;
  316.  
  317.     /* no errors, so return FALSE */
  318.     return( FALSE );
  319. }   /* end of init(); */
  320.  
  321.  
  322.  
  323. /************************************************************************
  324.  *
  325.  *  clean( why ) - This routine cleans everything up.
  326.  *
  327.  *  This code section was written by Robert E. Beaty and
  328.  *  are Copyright (C) 1987 by R.E.Beaty and The Man From S.P.U.D.
  329.  *
  330.  ************************************************************************/
  331. void clean( why )
  332. int why;
  333. {
  334.     /* Abort the timer request pending */
  335.     if ( timeReq.tr_node.io_Message.mn_ReplyPort != NULL )
  336.         AbortIO( (char *) &timeReq.tr_node );
  337.  
  338.     /* if we want a quick exit then skip this stuff */
  339.     if ( why == QUICK_EXIT ) goto quick;
  340.  
  341.     /* just call the clean up routines */
  342.     if ( timerPort != NULL ) DeletePort( timerPort );
  343.     CloseNarrator( why );
  344.     if ( clockPort != NULL ) DeletePort( clockPort );
  345.     quick:
  346.     if ( IntuitionBase != NULL ) CloseLibrary( IntuitionBase );
  347. }   /* end of clean(); */
  348.  
  349.  
  350.  
  351. /************************************************************************
  352.  *
  353.  *  bed_bye( how_much ) - This routine submits a timer event for us
  354.  *
  355.  *  This code section was written by Robert E. Beaty and
  356.  *  are Copyright (C) 1987 by R.E.Beaty and The Man From S.P.U.D.
  357.  *
  358.  ************************************************************************/
  359. void bed_bye( how_much )
  360. int how_much;
  361. {
  362.     /* See how long the sleep is for */
  363.     if ( how_much == LITTLE ) {
  364.         timeReq.tr_time.tv_secs = 5;        /* little is 5 sec. */
  365.         timeReq.tr_time.tv_micro = 0;
  366.     }
  367.     else {
  368.         timeReq.tr_time.tv_secs = 885;        /* big is 14 min 45 sec. */
  369.         timeReq.tr_time.tv_micro = 0;
  370.     }
  371.     /* ... and send it out to be done */
  372.     SendIO( (char *) &timeReq.tr_node ); 
  373. }   /* end of bed_bye(); */
  374.  
  375.  
  376.  
  377. /************************************************************************
  378.  *
  379.  *  speak_time( hrs, mins ) - This routine formats and speaks the time.
  380.  *
  381.  *  This code section was written by Robert E. Beaty and
  382.  *  are Copyright (C) 1987 by R.E.Beaty and The Man From S.P.U.D.
  383.  *
  384.  ************************************************************************/
  385. void speak_time( hrs, mins )
  386. int hrs, mins;
  387. {
  388.     /* 
  389.      * First, see if we need to prestart the speakers 
  390.      */
  391.     if ( prestart )
  392.         cp = stpcpy( alarm, "t,," );
  393.     else
  394.         cp = alarm;
  395.  
  396.     /*
  397.      * Build up the string to speak
  398.      */
  399.     /* start with the salutation */
  400.     cp = stpcpy( cp, salutation );
  401.     /* ... add the time is stuff */
  402.     cp = stpcpy( cp, ", It is now " );
  403.     /* check for quarter till */
  404.     if ( (alarm_mode == QUARTER_HOUR) && (mins == 45) ) {
  405.         cp = stpcpy( cp, "quarter till " );
  406.         /* check to see that it makes sense */
  407.         if ( (++hrs) == 13 ) hrs = 1;
  408.     }
  409.     /*
  410.      * always add the hour
  411.      */
  412.     switch( hrs ) {
  413.         case 1 : cp = stpcpy( cp, "1 " );  break;
  414.         case 2 : cp = stpcpy( cp, "2 " );  break;
  415.         case 3 : cp = stpcpy( cp, "3 " );  break;
  416.         case 4 : cp = stpcpy( cp, "4 " );  break;
  417.         case 5 : cp = stpcpy( cp, "5 " );  break;
  418.         case 6 : cp = stpcpy( cp, "6 " );  break;
  419.         case 7 : cp = stpcpy( cp, "7 " );  break;
  420.         case 8 : cp = stpcpy( cp, "8 " );  break;
  421.         case 9 : cp = stpcpy( cp, "9 " );  break;
  422.         case 10 : cp = stpcpy( cp, "ten " );  break;
  423.         /* the number 11 sounds better spelled 'eelaven' */
  424.         case 11 : cp = stpcpy( cp, "eelaven " );  break;
  425.         case 12 : cp = stpcpy( cp, "twelve " );  break;
  426.     }   /* end of decoding the hours */
  427.     /*
  428.      * decode the different modes
  429.      */
  430.     switch( alarm_mode ) {
  431.         case QUARTER_HOUR :
  432.             switch( mins ) {
  433.                 case 0 : cp = stpcpy( cp, "o'clock." );  break;
  434.                 case 15 : cp = stpcpy( cp, "fifteen." );  break;
  435.                 case 30 : cp = stpcpy( cp, "thirty." );  break;
  436.                 case 45 : cp = stpcpy( cp, "." );  break;
  437.                 /* if we aren't where we are supposed to be, NULL it out */
  438.                 default : cp = NULL;  break;
  439.             }
  440.             break;
  441.         case HALF_HOUR :
  442.             switch( mins ) {
  443.                 case 0 : cp = stpcpy( cp, "o'clock." );  break;
  444.                 case 30 : cp = stpcpy( cp, "thirty." );  break;
  445.                 /* if we aren't where we are supposed to be, NULL it out */
  446.                 default : cp = NULL;  break;
  447.             }
  448.             break;
  449.         case HOUR :
  450.             if ( mins == 0 )
  451.                 cp = stpcpy( cp, "o'clock." );
  452.             else
  453.                 /* if we aren't where we are supposed to be, NULL it out */
  454.                 cp = NULL;
  455.             break;
  456.     }   /* end of alarm_mode selection */
  457.  
  458.     /*
  459.      * If the time section is not NULL, do the rest
  460.      */
  461.     if ( cp != NULL ) {
  462.         /*
  463.          * ... add the "Good morning..." or "Good night..."
  464.          */
  465.         if ( start_alarm != end_alarm ) {
  466.             if ( alarm_time == start_alarm )
  467.                 cp = stpcpy( cp, ",, Good Morning!" );
  468.             if ( alarm_time == end_alarm )
  469.                 cp = stpcpy( cp, ",, Good Night." );
  470.         }   /* end of special salutation */
  471.  
  472.         /*
  473.          * translate it and speak it
  474.          */
  475.         rtnCode = Translate( alarm, strlen(alarm), outputString, 500 );
  476.         writeNarrator->sex = MALE;
  477.         writeNarrator->pitch = DEFPITCH;
  478.         writeNarrator->mode = ROBOTICF0;
  479.         writeNarrator->volume = alarm_volume;
  480.         writeNarrator->message.io_Data = (APTR)outputString;
  481.         writeNarrator->message.io_Length = strlen( outputString );
  482.         DoIO( writeNarrator );
  483.     }   /* end of finishing it up and speaking it */
  484. }   /* end of speak_time(); */
  485.  
  486.  
  487.  
  488. /************************************************************************
  489.  *
  490.  *  usage() - This routine helps the user.
  491.  *
  492.  *  This code section was written by Robert E. Beaty and
  493.  *  are Copyright (C) 1987 by R.E.Beaty and The Man From S.P.U.D.
  494.  *  
  495.  *  minimal additions by H. Bret Young 
  496.  *
  497.  ************************************************************************/
  498. usage( how_much )
  499. int how_much;
  500. {
  501.     cprintf( "Usage:\n" );
  502.     cprintf( "  run SPUDclock [-m greeting message] [-f] [-t] [-h] [-q] [-p] [-s ####] [-e ####] [-v ##]\n" );
  503.     if ( how_much == LITTLE ) return( FALSE );
  504.     cprintf( "Where:\n" );
  505.     cprintf( "  -m greeting message  - this will be spoken before the time\n" );
  506.     cprintf( "  -f  - this will cause the alarm to sound every quarter hour\n" );
  507.     cprintf( "  -t  - this will cause the alarm to sound every half hour\n" );
  508.     cprintf( "  -h  - this will cause the alarm to sound every hour\n" );
  509.     cprintf( "  -p  - this will make the alarm contain a 't' to start speakers\n" );
  510.     cprintf( "  -s #### - this will set the starting time to this time (2400 hr.)\n" );
  511.     cprintf( "  -e #### - this will set the ending time to this time (2400 hr.)\n" );
  512.     cprintf( "  -v ## - this will set the alarm volume to this (>0 and <=64)\n" );
  513.     cprintf( "  -q  - this will remove all copies of SPUDclock from memory\n" );
  514.     cprintf( "  -l  - this will list the current SPUDclock settings\n");
  515.     cprintf( "  -d  - this will cause the parameters not specified on the\n");
  516.     cprintf( "        command line to revert to their defaults\n");
  517.     return( FALSE );
  518. }   /* end of usage(); */
  519.  
  520. /************************************************************************
  521.  *
  522.  *  print_settings() - This routine prints the current SPUDclock settings
  523.  *
  524.  *  This section was written by H. Bret Young
  525.  *  are Copyright (C) 1987 by H. Bret Young and The Man From S.P.U.D.
  526.  *
  527.  ************************************************************************/
  528. void print_settings()
  529. {
  530.     char out[5];
  531.     
  532.     cprintf("SPUDclock settings \n\n");
  533.  
  534.     cprintf("  The alarm will sound  ");
  535.     switch (alarm_mode) {
  536.         case QUARTER_HOUR :
  537.             cprintf("every QUARTER HOUR\n");
  538.             break;
  539.         case HALF_HOUR :
  540.             cprintf("every HALF HOUR\n");
  541.             break;
  542.         case HOUR :
  543.             cprintf("every HOUR\n");
  544.             break;
  545.     }
  546.  
  547.     if (prestart)
  548.         cprintf("  The speakers WILL be prestarted\n");
  549.     else
  550.         cprintf("  The speakers WILL NOT be prestarted\n");
  551.  
  552.     cprintf("  The clock will begin at ");      
  553.     itoa(out,start_alarm);
  554.     cprintf(out); cprintf("\n");
  555.  
  556.     cprintf("  The clock will stop at ");    
  557.     itoa(out,end_alarm);
  558.     cprintf(out); cprintf("\n");
  559.  
  560.     cprintf("  The alarm volume is ");
  561.     itoa(out,alarm_volume);
  562.     cprintf(out); cprintf("\n");
  563.  
  564.     cprintf("  The alarm salutation is :\n");
  565.     cprintf("   ");
  566.     cprintf(salutation); cprintf("\n");
  567. }
  568.  
  569. /************************************************************************
  570.  *
  571.  *  Main section of SPUDclock...
  572.  *
  573.  *  This and all code sections were written by Robert E. Beaty and
  574.  *  H. Bret Young are Copyright (C) 1987 by H. Bret Young and R.E.Beaty
  575.  *  and The Man From S.P.U.D.
  576.  *
  577.  ************************************************************************/
  578. main( argc, argv )
  579. int argc;
  580. char *argv[];
  581. {
  582.     int i;
  583.     int change_flags,
  584.         changing,
  585.         listing;
  586.  
  587.     /*
  588.      *
  589.      *  Set the defaults
  590.      *
  591.      */
  592.     alarm_mode = HALF_HOUR;        /* do it every 30 minutes */
  593.     prestart = FALSE;            /* don't prestart the speakers */
  594.     start_alarm = 830;            /* start at 8:30 am */
  595.     end_alarm = 2300;            /* end at 11:00 pm */
  596.     alarm_volume = 50;            /* not too loud */
  597.     stpcpy( salutation, " " );        /* no salutation to start off */
  598.     cp = salutation;            /* this is for the argument processing */
  599.     quit_flag = FALSE;            /* we aren't stopping yet */
  600.     change_flags = 0;
  601.     changing = FALSE;
  602.     listing = FALSE;
  603.  
  604.     /*
  605.      *
  606.      *  Decode the arguments
  607.      *
  608.      */
  609.     for ( i=1; i < argc; i++ ) {
  610.         /* check the options */
  611.         if ( argv[i][0] == '-' ) {
  612.             /* decode the options */
  613.             switch( argv[i][1] ) {
  614.                 case 'f' :
  615.                     change_flags |= AM_BIT;
  616.                     alarm_mode = QUARTER_HOUR;
  617.                     break;
  618.                 case 't' :
  619.                     change_flags |= AM_BIT;
  620.                     alarm_mode = HALF_HOUR;
  621.                     break;
  622.                 case 'h' :
  623.                     change_flags |= AM_BIT;
  624.                     alarm_mode = HOUR;
  625.                     break;
  626.                 case 'q' :
  627.                     quit_flag = TRUE;
  628.                     break;
  629.                 case 'p' :
  630.                     change_flags |= PS_BIT;
  631.                     prestart = TRUE;
  632.                     break;
  633.                 case 's' :
  634.                     change_flags |= SA_BIT;
  635.                     i++;    /* move to the next argument, the time */
  636.                     start_alarm = 0;
  637.                     while((*argv[i] >= '0') && (*argv[i] <= '9'))
  638.                         start_alarm = (start_alarm * 10) + *argv[i]++ - '0';
  639.                     break;
  640.                 case 'e' :
  641.                     change_flags |= EA_BIT;
  642.                     i++;    /* move to the next argument, the time */
  643.                     end_alarm = 0;
  644.                     while((*argv[i] >= '0') && (*argv[i] <= '9'))
  645.                         end_alarm = (end_alarm * 10) + *argv[i]++ - '0';
  646.                     break;
  647.                 case 'v' :
  648.                     change_flags |= AV_BIT;
  649.                     i++;    /* move to the next argument, the volume */
  650.                     alarm_volume = 0;
  651.                     while((*argv[i] >= '0') && (*argv[i] <= '9'))
  652.                         alarm_volume = (alarm_volume * 10) + *argv[i]++ - '0';
  653.                     break;
  654.                 case 'm' :
  655.                     change_flags |= S_BIT;
  656.                     /* read in the salutation a word at a time */
  657.                     for ( i=i; (argv[i+1][0] != '-') && (i < argc); i++ ) {
  658.                         cp = stpcpy( cp, argv[i+1] );
  659.                         cp = stpcpy( cp, " ");
  660.                     }    
  661.                     break;
  662.                 case 'l' :
  663.                     listing = TRUE;
  664.                     break;
  665.                 case 'd' :
  666.                     changing = TRUE;
  667.                     break;
  668.                 default :
  669.                     usage( LITTLE );    /* show him the small usage */
  670.                     exit( TRUE );
  671.                     break;
  672.             }   /* end of decoding the options */
  673.         }   /* end of checking the options */
  674.         else {
  675.             usage( BIG );    /* he needs lots of help */
  676.             exit( TRUE );
  677.         }
  678.     }   /* end of decoding the arguments */
  679.  
  680.     /*
  681.      * 
  682.      *  O.K. all arguments are decoded, so let's see if one copy of
  683.      *  SPUDclock already exists 
  684.      *
  685.      */
  686.     /* Assume one does and do just a quick start */
  687.     if ( (error=init( QUICK_START )) != FALSE ) {
  688.         if ( error == CANT_OPEN_INTUITION ) {
  689.             cprintf( "Sorry, but I cannot open a copy of Intuition!\n" );
  690.             cprintf( "Please check your DEVS: directory or reboot.\n" );
  691.         }    /* end of printing the error message */
  692.         exit( error );
  693.     }   /* end of error checking for the initial start */
  694.     clockPort = (struct MsgPort *) FindPort( "SPUDclock" );
  695.     if ( clockPort != NULL ) {
  696.         /* Allocate the memory for the message to the other SPUDclock */
  697.         outgoing = (struct PacketMessage *) AllocMem( sizeof(struct PacketMessage), MEMF_PUBLIC );
  698.         if ( outgoing == NULL ) {
  699.             cprintf( "Sorry, There is not enough memory to send the message\n" );
  700.             cprintf( "to the running copy of SPUDclock. You will probably\n" );
  701.             cprintf( "have to re-boot the machine to change the running copy\n" );
  702.             cprintf( "of SPUDclock.\n" );
  703.             clean( QUICK_EXIT );
  704.             exit( TRUE );
  705.         }   /* end of error checking the message allocation */
  706.  
  707.         /* Allocate the reply port for this message */
  708.         replyPort = (struct MsgPort *) CreatePort( "SPUDclock.reply.port", TASK_PRIORITY );
  709.         if ( replyPort == NULL ) {
  710.             cprintf( "Sorry, There are not enough free resources to send the\n" );
  711.             cprintf( "message to the running copy of SPUDclock. You will probably\n" );
  712.             cprintf( "have to re-boot the machine to change the running copy\n" );
  713.             cprintf( "of SPUDclock.\n" );
  714.             /* free everything up */
  715.             FreeMem( outgoing, sizeof(struct PacketMessage) );
  716.             clean( QUICK_EXIT );
  717.             exit( TRUE );
  718.         }   /* end of error checking for port creation */
  719.  
  720.         /*
  721.          * Now set this message packet so that it will do the job
  722.          */
  723.         outgoing->packet_message.mn_Node.ln_Type = NT_MESSAGE;
  724.         outgoing->packet_message.mn_ReplyPort = replyPort;
  725.         outgoing->packet_message.mn_Length = sizeof( struct PacketMessage );
  726.         /* Get the status from the packet */
  727.         outgoing->alarm_mode = alarm_mode;
  728.         outgoing->prestart = prestart;
  729.         outgoing->start_alarm = start_alarm;
  730.         outgoing->end_alarm = end_alarm;
  731.         outgoing->alarm_volume = alarm_volume;
  732.         stpcpy( outgoing->salutation, salutation );
  733.         outgoing->quit_flag = quit_flag;
  734.         outgoing->change_flags = change_flags;
  735.         outgoing->changing = changing;
  736.         outgoing->listing = listing;
  737.         
  738.  
  739.         /*
  740.          * Send it, wait for a reply, and then dispose of all of it
  741.          */
  742.         PutMsg( clockPort, outgoing );
  743.         WaitPort( replyPort );
  744.         /* free everything up */
  745.         DeletePort( replyPort );
  746.         FreeMem( outgoing, sizeof(struct PacketMessage) );
  747.         clean( QUICK_EXIT );
  748.         exit( TRUE );
  749.     }   /* end of passing arguments to the running SPUDclock */
  750.  
  751.     /* Print a copyright notice */
  752.     cprintf( "SPUDclock v1.2 - Copyright 1987 by The Man From S.P.U.D.\n" );
  753.     
  754.     if (listing) print_settings();
  755.  
  756.     /* If quitting was our only motive, then quit */
  757.     if ( quit_flag ) {
  758.         clean( QUICK_EXIT );
  759.         exit( FALSE );
  760.     }   /* end of quick quit */
  761.  
  762.     /* We need to do a normal start */
  763.     if ( (error=init( NORMAL_START )) != FALSE ) {
  764.         /* decode the error */
  765.         switch ( error ) {
  766.             case CANT_OPEN_INTUITION :
  767.                 cprintf( "Sorry, but I cannot open a copy of Intuition!\n" );
  768.                 cprintf( "Please check your DEVS: directory or reboot.\n" );
  769.                 break;
  770.             case CANT_OPEN_TRANSLATOR :
  771.                 cprintf( "Sorry, but I cannot open a copy of the\n" );
  772.                 cprintf( "Translator device! Please check your DEVS:\n" );
  773.                 cprintf( "directory for the narrator.device file\n" );
  774.                 cprintf( "and/or reboot.\n" );
  775.                 break;
  776.             case CANT_OPEN_NARRATOR :
  777.                 cprintf( "Sorry, but I cannot open a copy of the\n" );
  778.                 cprintf( "Narrator device! Please check your DEVS:\n" );
  779.                 cprintf( "directory for the narrator.device file\n" );
  780.                 cprintf( "and/or reboot.\n" );
  781.                 break;
  782.             case CANT_OPEN_TIMER :
  783.                 cprintf( "Sorry, but I cannot open a copy of the\n" );
  784.                 cprintf( "Timer device! Please check your DEVS:\n" );
  785.                 cprintf( "directory and/or reboot.\n" );
  786.                 break;
  787.             case CREATE_PORT_PROBLEMS :
  788.                 cprintf( "Sorry, There are not enough free resources to open the\n" );
  789.                 cprintf( "message ports required. You will probably have to re-boot\n" );
  790.                 cprintf( "the machine to run SPUDclock.\n" );
  791.                 break;
  792.             case CREATE_IO_PROBLEMS :
  793.                 cprintf( "Sorry, There are not enough free resources to open the\n" );
  794.                 cprintf( "I/O ports required. You will probably have to re-boot\n" );
  795.                 cprintf( "the machine to run SPUDclock.\n" );
  796.                 break;
  797.             case TRANSLATOR_NOT_WORKING :
  798.                 cprintf( "Sorry, but the Translator device does not seem to be working\n" );
  799.                 cprintf( "at this time. The only suggestion is to re-boot the machine\n" );
  800.                 cprintf( "and/or get a fresh copy of narrator.device into DEVS:.\n" );
  801.                 break;
  802.             default :
  803.                 cprintf( "Sorry, but SPUDclock has returned an error.\n" );
  804.                 cprintf( "Please try running it again.\n" );
  805.                 break;
  806.         }   /* end of decoding the error and printing the error message */
  807.         exit( error );
  808.     }   /* end of error checking the start-up of the original copy */
  809.  
  810.  
  811.     /* Submit a little sleep */
  812.     bed_bye( LITTLE );
  813.  
  814.     while( TRUE ) {
  815.         /*
  816.          *  Now wait until something wakes us up
  817.          */
  818.         signal = Wait( timer_signal | port_signal );
  819.         /*
  820.          *
  821.          * ... check the timer
  822.          *
  823.          */
  824.         if ( signal & timer_signal ) {
  825.             /* get the message out of the way */
  826.             (void) GetMsg( timerPort );
  827.             /* Get the time now */
  828.             DateStamp( &now );
  829.             /* Get the time into hours and minutes */
  830.             hours_24 = now.ds_Minute / 60;
  831.             hours_12 = ( now.ds_Minute / 60 ) % 12;
  832.             if ( hours_12 == 0 ) hours_12 = 12;        /* make it simple 12 hour */
  833.             minutes = now.ds_Minute % 60;
  834.             /*
  835.              *  See if we are synced up yet
  836.              */
  837.             if ( (minutes == 0) || (minutes == 15) || (minutes == 30) || (minutes == 45) ) {
  838.                 /* submit a nice long wake up call */
  839.                 bed_bye( BIG );
  840.                 /*
  841.                  *  Now see if we need to output this to the speakers
  842.                  */
  843.                 alarm_time = hours_24 * 100 + minutes;
  844.                 if ( (alarm_time >= start_alarm) && (alarm_time <= end_alarm) )
  845.                     speak_time( hours_12, minutes );
  846.             }   /* end of processing for synced up */
  847.             else {
  848.                 /* submit another wake up call soon */
  849.                 bed_bye( LITTLE );
  850.             }   /* end of processing for not synced up */
  851.         }   /* end of processing the timer signal */
  852.  
  853.         /*
  854.          *
  855.          * ... check the clock port 
  856.          *
  857.          */
  858.         if ( signal & port_signal ) {
  859.             /* Get the message */
  860.             incoming = (struct PacketMessage *) GetMsg( clockPort );
  861.             /* Get the status from the packet */
  862.             
  863.             changing = incoming->changing;
  864.             change_flags = incoming->change_flags;
  865.             listing = incoming->listing;
  866.             quit_flag = incoming->quit_flag;
  867.  
  868.             switch (changing) {
  869.                 case FALSE :
  870.                     if (change_flags & AM_BIT)
  871.                     alarm_mode = incoming->alarm_mode;
  872.                     if (change_flags & PS_BIT)
  873.                         prestart = incoming->prestart;
  874.                     if (change_flags & SA_BIT)
  875.                     start_alarm = incoming->start_alarm;
  876.                     if (change_flags & EA_BIT)
  877.                     end_alarm = incoming->end_alarm;
  878.                     if (change_flags & AV_BIT)
  879.                         alarm_volume = incoming->alarm_volume;
  880.                     if (change_flags & S_BIT)
  881.                     stpcpy( salutation, incoming->salutation );
  882.                 break;
  883.             case TRUE :
  884.                 alarm_mode = incoming->alarm_mode;
  885.                     prestart = incoming->prestart;
  886.                 start_alarm = incoming->start_alarm;
  887.                 end_alarm = incoming->end_alarm;
  888.                     alarm_volume = incoming->alarm_volume;
  889.                 stpcpy( salutation, incoming->salutation );
  890.                 break;
  891.         }
  892.  
  893.             if (listing) print_settings();
  894.  
  895.             /* since we didn't allocate this message, we must reply */
  896.             ReplyMsg( incoming );
  897.             
  898.             /*
  899.              * If the quit flag is set then we need to leave
  900.              */
  901.             if ( quit_flag ) {
  902.                 clean( NORMAL_EXIT );    /* clean all this up */
  903.                 exit( FALSE );
  904.             }   /* end of quitting */
  905.  
  906.         }   /* end of processing the port signal */
  907.     }   /* end of main loop */    
  908.  
  909.     /* we need this to keep the compiler happy */
  910.     return( FALSE );
  911. }   /* end of SPUDclock(); */
  912.